from functools import wraps

from django.http import HttpRequest
from rest_framework.request import Request
from rest_framework import exceptions
from django.core.exceptions import PermissionDenied


def required_data_fields(required_fields):
    """
    检查body参数是否满足要求
    """

    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(obj, *args, **kwargs):
            request = obj
            if not isinstance(obj, HttpRequest) and not isinstance(obj, Request):
                request = args[0]

            for field in required_fields:
                if field not in request.data or request.data[field] is None:
                    raise exceptions.ValidationError({field: f'Missing parameter: {field}'})

            return view_func(obj, *args, **kwargs)

        return _wrapped_view

    return decorator


def required_query_parameters(required_fields):
    """
    检查 url 查询参数是否满足要求
    """

    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(obj, *args, **kwargs):
            request = obj
            if not isinstance(obj, HttpRequest) and not isinstance(obj, Request):
                request = args[0]

            parameters = request.query_params
            for field in required_fields:
                if field not in parameters or not parameters[field]:
                    raise exceptions.ParseError('参数错误：{}'.format(field))
            return view_func(obj, *args, **kwargs)

        return _wrapped_view

    return decorator


def permission_required(required_permissions):
    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(obj, *args, **kwargs):
            request = obj
            if not isinstance(obj, HttpRequest) and not isinstance(obj, Request):
                request = args[0]
            permissions = request.user.get_permissions()
            if not (set(permissions) & set(required_permissions)):
                raise PermissionDenied
            return view_func(obj, *args, **kwargs)
        return _wrapped_view
    return decorator
